local japi = require 'jass.japi'
local jass = require 'jass.common'
local message = require 'jass.message'

--- 用来存放所有的世界坐标控件
local world_controls = {}


local anchor_map = {
    topleft         = 0,
    top             = 1,
    topright        = 2,
    left            = 3,
    center          = 4,
    right           = 5,
    bottomleft      = 6,
    bottom          = 7,
    bottomright     = 8,
}

--- 补充 --- 
local api = class.ui_base

--- 锚点
api.world_anchor = 'bottom'

--- 自动删除世界控件
api.world_auto_remove = true

class.ui_base.class = {
    panel = class.panel,
    button = class.button,
}

--- 添加控件
-- function api:add(frametype, ...)
--     local frameclass = class.ui_base.class[frametype]
--     if frameclass and frameclass.create then 
--         local ui = frameclass:create(self, ...)
--         if package.local_test then 
--             local info = debug.getinfo(4, "Sl") or {}
--             local bool = info.short_src:find('core')
--             --- 不是底层创建的控件记录路径用来热更新
--             if not bool then 
--                 ui._src = info.short_src
--                 ui._line = info.currentline
--             end 
--         end 
--         return ui
--     end 
-- end 

--- 获取指定锚点相对偏移 以0,0,控件宽,高 坐标起始点以及终点
--- is_negation 是否取反 anchor 左 返回 右 的值
function api:get_anchor_offset(anchor, is_negation)
    anchor = anchor_map[anchor] or 0
    if is_negation then 
        anchor = math.abs(8 - anchor) 
    end 
    if anchor == 0 then 
        return 0, 0
    elseif anchor == 1 then 
        return self.w / 2, 0
    elseif anchor == 2 then 
        return self.w, 0
    elseif anchor == 3 then 
        return 0, self.h / 2
    elseif anchor == 4 then 
        return self.w / 2, self.h / 2
    elseif anchor == 5 then 
        return self.w, self.h / 2
    elseif anchor == 6 then 
        return 0, self.h
    elseif anchor == 7 then 
        return self.w / 2, self.h
    elseif anchor == 8 then 
        return self.w, self.h
    end 
    return 0, 0
end

--- 获取实际坐标 父控件坐标 + 子控件偏移
function api:get_real_position()
    local ox,oy = 0,0
    local object = self 
    while not object:is_simple() do
        ox = ox + (object.x or 0)
        oy = oy + (object.y or 0)
        if object.parent == nil then 
            break
        end
        object = object.parent
    end
    return ox,oy
end

--- 设置实际坐标位置 坐标 - 父控件坐标 = 子控件偏移
function api:set_real_position(x, y, anchor)
    if anchor then 
        local offect_x, offect_y = self:get_anchor_offset(anchor)
        x = x + offect_x
        y = y + offect_y
    end 
    local rx, ry = self:get_real_position()
    x = x - (rx - self.x) 
    y = y - (ry - self.y)
    self:set_position(x, y)
end

--- 获取锚点偏移位置
function api:get_anchor_offset_position(anchor, is_negation)
    local x, y = self:get_real_position()
    local ox, oy = self:get_anchor_offset(anchor, is_negation)
    return x + ox, y + oy 
end

--- 设置锚点位置, 
--- @params self 自己
--- @params self_anchor 自己的锚点
--- @params target 目标
--- @params target_anchor 目标的锚点
--- @params x 相对偏移x轴
--- @params y 相对偏移y轴
function api:set_anchor_position(self_anchor, target, target_anchor, x, y)
    x = x or 0 
    y = y or 0
    local self_x, self_y = self:get_anchor_offset(self_anchor)
    local target_x, target_y = target:get_anchor_offset_position(target_anchor)
    self:set_real_position(target_x - self_x + x,target_y - self_y + y)
end

--- 设置指定控件跟随自身
function api:set_tooltip_follow(tooltip, anchor, offset_x, offset_y)
    local self_x, self_y = self:get_anchor_offset_position(anchor)

    local w, h = tooltip:get_anchor_offset(anchor, true)

    local x, y = self_x + (offset_x or 0), self_y + (offset_y or 0)
    x = x - w
    y = y - h
    x = math.max(0,math.min(1920 - tooltip.w, x))
    y = math.max(0,math.min(1080 - tooltip.h, y))
    tooltip:set_real_position(x, y)
end

-- --- 绑定物体
-- function api:bind_widget(widget,anchor)
--     if not self:get_parent():is_simple() then 
--         log.error('必须是底层控件才能绑定世界坐标')
--         return 
--     end
--     self.world_width = self.w 
--     self.world_height = self.h
--     self.bind_world = true 
--     self.world_widget = widget
--     self.world_anchor = anchor
--     world_controls[self] = true
-- end

--- 绑定世界坐标
function api:set_world_position(x,y,z,anchor)
    if not self:get_parent():is_simple() then 
        log.error('必须是底层控件才能绑定世界坐标')
        return 
    end
    self.world_width = self.w 
    self.world_height = self.h
    self.bind_world = true 
    self.world_widget = nil
    self.world_x = x or 0
    self.world_y = y or 0
    self.world_z = z or 0
    self.world_anchor = anchor
    world_controls[self] = true
end

-- --- 解除绑定
-- function api:unbind_world()
--     self.bind_world = false 
--     self.world_widget = nil
--     self.world_type = nil
--     world_controls[self] = nil
-- end



-- ac.hardware:on "窗口大小刷新" (function()
--     for _, frame in pairs(class.ui_base.allframes) do 
--         if frame.relocation then 
--             frame:relocation()
--         end 
--     end 
-- end)

-- local function get_collision(widget)
--     if not widget.get_collision then 
--         return 32
--     end
--     return widget:get_collision()
-- end 

-- local function get_model_scale(widget)
--     if not widget.get_slk then 
--         return 1
--     end 
--     return widget:get_slk ('scale',1.0)
-- end 

-- local function get_scale(widget)
--     if not widget.get_scale then 
--         return 1
--     end 
--     return widget:get_scale()
-- end 

-- local function unit_overhead(widget)
--     if widget.type == 'unit' then 
--         return ac.message.unit_overhead(widget.handle)
--     end 
--     return 0 
-- end 

-- local function get_height(widget)
--     return widget:get_height()
-- end 

-- local ffi = require 'ffi'

-- local function get_point(unit)
--     local addr = japi.GetUnitAddress(unit.handle)
--     local value1 = ffi.cast("float*", addr + 0x284)
--     local value2 = ffi.cast("float*", addr + 0x288)
--     return ac.point(value1[0], value2[0])
-- end 


-- 然后 addr 偏移 0x284 0x288



-- ac.hardware:on '界面绘制' (function()
    
--     for frame in pairs(world_controls) do 
--         local widget = frame.world_widget 
--         local x, y, z 
--         if widget then 
--             if widget.removed then
--                 if frame.world_auto_remove then 
--                     frame:remove()
--                 else 
--                     frame:hide()
--                 end
--                 goto continue
--             else 
--                 if widget.in_worldscreen and not widget:in_worldscreen() then 
--                     frame:hide()
--                     goto continue
--                 else 
--                     x = jass.GetWidgetX(widget.handle)
--                     y = jass.GetWidgetY(widget.handle)
--                     z = ac.point.get_location_height(x, y) + get_height(widget) + unit_overhead(widget) * get_scale(widget)
--                 end 
--             end 
--         else 
--             x, y, z = frame.world_x, frame.world_y, frame.world_z
--         end 
--         local screen_x, screen_y, scale = class.ui_base.w2s(x, y, z)
--         if screen_x == nil or screen_x < 0 or screen_y < 32 or screen_x > 1920 or screen_y > 768 then 
--             frame:hide()
--         else 
--             frame:show()
--             if widget then 
--                 frame:set_width( frame.world_width  * ( get_model_scale(widget)  ) )
--             end
--             local x = screen_x - frame.w
--             local y = screen_y - frame.h 
--             frame:set_real_position(x, y, frame.world_anchor)
--             -- * scale 
--         end 
--         ::continue::
--     end
-- end)
